#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>

// Step 1: 定义抽象享元类 (Flyweight)
class Character {
public:
    virtual ~Character() = default;

    // 显示字符
    virtual void display(int x, int y) const = 0;

protected:
    char symbol_;    // 内在状态：字符本身
    std::string font_; // 内在状态：字体
};

// Step 2: 实现具体享元类 (Concrete Flyweight)
class ConcreteCharacter : public Character {
public:
    ConcreteCharacter(char symbol, const std::string& font) {
        symbol_ = symbol;
        font_ = font;
    }

    void display(int x, int y) const override {
        std::cout << "Character '" << symbol_ << "' with font '" << font_ 
                  << "' displayed at (" << x << ", " << y << ")." << std::endl;
    }
};

// Step 3: 定义享元工厂 (Flyweight Factory)
class CharacterFactory {
private:
    std::unordered_map<char, std::shared_ptr<Character>> characters_; // 缓存共享的字符

public:
    std::shared_ptr<Character> getCharacter(char symbol, const std::string& font) {
        // 如果字符已存在，则直接返回
        if (characters_.find(symbol) != characters_.end()) {
            return characters_[symbol];
        }

        // 如果字符不存在，则创建并存储
        auto character = std::make_shared<ConcreteCharacter>(symbol, font);
        characters_[symbol] = character;
        return character;
    }
};

// Step 4: 客户端代码
int main() {
    CharacterFactory factory;

    // 获取共享字符对象
    auto charA = factory.getCharacter('A', "Arial");
    auto charB = factory.getCharacter('B', "Arial");
    auto charC = factory.getCharacter('A', "Arial"); // 重复获取 'A'，应复用

    // 显示字符（外在状态为坐标）
    charA->display(10, 20);
    charB->display(15, 25);
    charC->display(30, 40); // 实际复用了 charA

    // 检查共享是否生效
    std::cout << "Are charA and charC the same instance? "
              << (charA == charC ? "Yes" : "No") << std::endl;

    return 0;
}


